/*
 * MoveToFront.cpp
 *
 *  Created on: 22/04/2011
 *      Author: ehpalumbo
 */

#include <MoveToFront.h>
#include <CharDataUnit.h>
#include <Logging.h>
#include <algorithm>

using namespace chardataunits;
using namespace logging;

namespace processes {


bool MoveToFrontForwardTransformationProcess::compareDataUnits(DataUnit* first, DataUnit* second) {
//	Logger& logger = LoggerFactory::getInstance().getLogger("processes.mtf");
//	logger.log(logging::TRACE, "Comparison between data units.");
	return (*first) < (*second);
}


MoveToFrontForwardTransformationProcess::MoveToFrontForwardTransformationProcess(vector<DataUnit*>& dataUnits) {
	Logger& logger = LoggerFactory::getInstance().getLogger("processes.mtf");
	logger.log(logging::DEBUG, "Building MTF FW Process...");
	logger.log(logging::DEBUG, "Creating 'dataUnitsList'.");
	this->dataUnitsList = new list<DataUnit*>;
	// Pass the DataUnits to our list.
	logger.log(logging::DEBUG, "Passing provided data units pointers to internal container.");
	for (vector<DataUnit*>::iterator it = dataUnits.begin();
			it != dataUnits.end(); it++) {
		this->dataUnitsList->push_front(*it);
	}
	logger.log(logging::DEBUG, "Ordering the generated list.");
	// Order our list to get it ready to start processing.
	this->dataUnitsList->sort(compareDataUnits);
	logger.log(logging::DEBUG, "MTF process ready to proceed.");
}

DataUnit* MoveToFrontForwardTransformationProcess::process(const DataUnit* dataUnit) {
	unsigned char result = 0;
	bool found = false;
	for (list<DataUnit*>::iterator it = this->dataUnitsList->begin();
			((it != this->dataUnitsList->end()) && (!found)); it++) {
		if ((*(*it)) == *dataUnit) {
			// Set the flag on.
			found = true;
			// Do move to front.
			this->dataUnitsList->splice(
					this->dataUnitsList->begin(), *(this->dataUnitsList), it);
		} else {
			result++;
		}
	}
	// TODO Handle error if we don't find the character... That shouldn't happen, but...
	return new CharDataUnit(result);
}

MoveToFrontForwardTransformationProcess::~MoveToFrontForwardTransformationProcess() {
	this->dataUnitsList->clear();
	delete this->dataUnitsList;
}

//Backward process

bool MoveToFrontBackwardTransformationProcess::compareDataUnits(DataUnit* first, DataUnit* second) {
	Logger& logger = LoggerFactory::getInstance().getLogger("processes.mtf");
	logger.log(logging::TRACE, "Comparison between data units.");
	return (*first) < (*second);
}


MoveToFrontBackwardTransformationProcess::MoveToFrontBackwardTransformationProcess(vector<DataUnit*>& dataUnits) {
	Logger& logger = LoggerFactory::getInstance().getLogger("processes.mtf");
	logger.log(logging::DEBUG, "Building MTF FW Process...");
	logger.log(logging::DEBUG, "Creating 'dataUnitsList'.");
	this->dataUnitsList = new list<DataUnit*>;
	// Pass the DataUnits to our list.
	logger.log(logging::DEBUG, "Passing provided data units pointers to internal container.");
	for (vector<DataUnit*>::iterator it = dataUnits.begin();
			it != dataUnits.end(); it++) {
		this->dataUnitsList->push_front(*it);
	}
	logger.log(logging::DEBUG, "Ordering the generated list.");
	// Order our list to get it ready to start processing.
	this->dataUnitsList->sort(compareDataUnits);
	logger.log(logging::DEBUG, "MTF process ready to proceed.");
}

DataUnit* MoveToFrontBackwardTransformationProcess::process(const DataUnit* dataUnit) {
	unsigned int position = dataUnit->asInt();
	list<DataUnit*>::iterator it = this->dataUnitsList->begin();
	for (unsigned int i = 0; i < position; it++){i++;}
	this->dataUnitsList->splice(
			this->dataUnitsList->begin(), *(this->dataUnitsList), it);
	return new CharDataUnit((**it).asInt());
}

MoveToFrontBackwardTransformationProcess::~MoveToFrontBackwardTransformationProcess() {
	this->dataUnitsList->clear();
	delete this->dataUnitsList;
}

}
